package com.easylinkin.sm.service.impl;

import com.easylinkin.sm.constant.CustomerConstant.Data;
import com.easylinkin.sm.constant.CustomerConstant.Error;
import com.easylinkin.sm.constant.LogConstant.Fields;
import com.easylinkin.sm.entity.Customer;
import com.easylinkin.sm.repository.CustomerRepository;
import com.easylinkin.sm.service.CustomerService;

import static com.easylinkin.sm.constant.CustomerConstant.Caches.ACTIVE_CUSTOMER;

import java.util.ArrayList;
import java.util.List;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.Root;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import site.morn.boot.data.DisplayableServiceSupport;
import site.morn.boot.jpa.SpecificationFunction;
import site.morn.cache.CacheGroup;
import site.morn.core.CriteriaMap;
import site.morn.exception.ApplicationMessages;
import site.morn.framework.context.AccountContext;
import site.morn.log.OperateArguments;
import site.morn.rest.RestModel;

/**
 * 客户服务实现
 *
 * @author majintao
 * @since 1.0.0, , 2019-08-16-10:34
 */
@Slf4j
@Transactional
@Service
public class CustomerServiceImpl extends
    DisplayableServiceSupport<Customer, Long, CustomerRepository>
    implements CustomerService {

  @Override
  public void active(Long id) {
    String username = AccountContext.currentUsername();
    CacheGroup cacheGroup = AccountContext.cacheGroup();
    Customer customer = get(id);
    cacheGroup.put(ACTIVE_CUSTOMER, username, customer);
  }

  @Override
  protected SpecificationFunction searchSpecificationFunction(Customer model, CriteriaMap attach) {
    // 过滤当前登录用户的客户
    model.setId(1L);
    return (reference, restrain, predicate) -> {
      Root root = reference.root();
      CriteriaBuilder builder = reference.builder();
      reference.query().orderBy(builder.desc(root.get(Fields.MODIFYTIME)));
      restrain.appendAnd(predicate.contain(Customer.Fields.name))
          .appendAnd(predicate.eq(Customer.Fields.display))
          .appendAnd(predicate.eq(Customer.Fields.id).not());
    };
  }

  @Override
  public <S extends Customer> S add(RestModel<S> restModel) {
    S customer = restModel.getModel();
    Customer findCustomer = repository().findFirstByNameAndDisplay(customer.getName(),
        Data.DISPLAY_SHOW);
    if (null != findCustomer && !findCustomer.getId().equals(customer.getId())) {
      OperateArguments.add(customer.getName());
      throw ApplicationMessages.translate(Error.NAME_REPEAT).exception();
    } else {
      customer.setDisplay(Data.DISPLAY_SHOW);
      customer.setLocked(Data.LOCK_NO);
      repository().save(customer);
    }
    OperateArguments.add(customer.getName());
    return customer;
  }

  @Override
  public <S extends Customer> S update(RestModel<S> restModel) {
    OperateArguments.add(restModel.getModel().getName());
    return super.update(restModel);
  }

  @Override
  public Customer toggleLock(Long id, boolean locked) {
    Customer customer = this.get(id);
    customer.setLocked(locked);
    OperateArguments.add(customer.getName());
    this.update(customer);
    return customer;
  }

  @Override
  public List<Customer> searchAll() {
    List<Customer> list = new ArrayList();
    if (AccountContext.isAdmin()) {
      list = repository().findAllByDisplay(Data.DISPLAY_SHOW);
    } else {
      list.add(AccountContext.current(Customer.class));
    }
    return list;
  }
}
